{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. PP-LCNet 模型简介\n",
    "PP-LCNet 系列模型是 PaddleCV 团队提出的轻量级卷积神经网络模型，该系列模型针对 Intel CPU 硬件平台特别优化，同时兼顾多种平台，在模型推理速度和精度之间取得了很好的平衡，实现了速度更快、准确率更高的轻量级骨干网络，同时也能提高目标检测、语义分割等下游视觉任务的效果。在 ImageNet1k 数据集上，PPLCNet 系列模型与其他轻量级网络的对比效果如下图所示。\n",
    "\n",
    "<div align=\"center\">\n",
    "<img src=\"https://user-images.githubusercontent.com/12560511/200731336-917cfa94-8470-4ac5-97a3-1f0d686a8f44.png\"  width = \"80%\"  />\n",
    "</div>\n",
    "\n",
    "\n",
    "PP-LCNet 系列模型基于 PaddleClas 开发、训练，更多关于 PP-LCNet 系列模型的更多信息，可以从 [PaddleClas-PPLCNet](https://github.com/paddlepaddle/paddleclas/blob/release%2F2.5/docs/zh_CN/models/ImageNet1k/PP-LCNet.md) 获取。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 模型效果\n",
    "\n",
    "我们在图像分类、目标检测、语义分割任务上评测了 PP-LCNet 系列模型的效果。\n",
    "\n",
    "### 2.1 图像分类\n",
    "\n",
    "PP-LCNet 系列模型在 ImageNet1k 数据集上的评测指标如下所示：\n",
    "\n",
    "| Model | Params(M) | FLOPs(M) | Top-1 Acc(\\%) | Top-5 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
    "| PPLCNet_x0_25  | 1.5 | 18  | 51.86 | 75.65 | 1.74 |\n",
    "| PPLCNet_x0_35  | 1.6 | 29  | 58.09 | 80.83 | 1.92 |\n",
    "| PPLCNet_x0_5   | 1.9 | 47  | 63.14 | 84.66 | 2.05 |\n",
    "| PPLCNet_x0_75  | 2.4 | 99  | 68.18 | 88.30 | 2.29 |\n",
    "| PPLCNet_x1_0     | 3.0 | 161 | 71.32 | 90.03 | 2.46 |\n",
    "| PPLCNet_x1_5   | 4.5 | 342 | 73.71 | 91.53 | 3.19 |\n",
    "| PPLCNet_x2_0     | 6.5 | 590 | 75.18 | 92.27 | 4.27 |\n",
    "| PPLCNet_x2_5   | 9.0 | 906 | 76.60 | 93.00 | 5.39 |\n",
    "| PPLCNet_x0_5_ssld | 1.9 | 47  | 66.10 | 86.46 | 2.05 |\n",
    "| PPLCNet_x1_0_ssld | 3.0 | 161 | 74.39 | 92.09 | 2.46 |\n",
    "| PPLCNet_x2_5_ssld | 9.0 | 906 | 80.82 | 95.33 | 5.39 |\n",
    "\n",
    "其中 `_ssld` 表示使用 `SSLD 蒸馏`后的模型。关于 `SSLD蒸馏` 的内容，详情 [SSLD 蒸馏](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.5/docs/zh_CN/training/advanced/knowledge_distillation.md)。\n",
    "\n",
    "与其他轻量级网络的性能对比：\n",
    "\n",
    "| Model | Params(M) | FLOPs(M) | Top-1 Acc(\\%) | Top-5 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
    "| MobileNetV2_x0_25  | 1.5 | 34  | 53.21 | 76.52 | 2.47 |\n",
    "| MobileNetV3_small_x0_35  | 1.7 | 15  | 53.03 | 76.37 | 3.02 |\n",
    "| ShuffleNetV2_x0_33  | 0.6 | 24  | 53.73 | 77.05 | 4.30 |\n",
    "| <b>PPLCNet_x0_25<b>  | <b>1.5<b> | <b>18<b>  | <b>51.86<b> | <b>75.65<b> | <b>1.74<b> |\n",
    "| MobileNetV2_x0_5  | 2.0 | 99  | 65.03 | 85.72 | 2.85 |\n",
    "| MobileNetV3_large_x0_35  | 2.1 | 41  | 64.32 | 85.46 | 3.68 |\n",
    "| ShuffleNetV2_x0_5  | 1.4 | 43  | 60.32 | 82.26 | 4.65 |\n",
    "| <b>PPLCNet_x0_5<b>   | <b>1.9<b> | <b>47<b>  | <b>63.14<b> | <b>84.66<b> | <b>2.05<b> |\n",
    "| MobileNetV1_x1_0 | 4.3 | 578  | 70.99 | 89.68 | 3.38 |\n",
    "| MobileNetV2_x1_0 | 3.5 | 327  | 72.15 | 90.65 | 4.26 |\n",
    "| MobileNetV3_small_x1_25  | 3.6 | 100  | 70.67 | 89.51 | 3.95 |\n",
    "| <b>PPLCNet_x1_0<b>     |<b> 3.0<b> | <b>161<b> | <b>71.32<b> | <b>90.03<b> | <b>2.46<b> |\n",
    "\n",
    "### 2.2 目标检测\n",
    "\n",
    "目标检测的方法选用了百度自研的 PicoDet，该方法主打轻量级目标检测场景，下表展示了在 COCO 数据集上、backbone 选用 PP-LCNet 与 MobileNetV3 的结果的比较，无论在精度还是速度上，PP-LCNet 的优势都非常明显。\n",
    "\n",
    "| Backbone | mAP(%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|\n",
    "| MobileNetV3_large_x0_35 | 19.2 | 8.1 |\n",
    "| <b>PPLCNet_x0_5<b> | <b>20.3<b> | <b>6.0<b> |\n",
    "| MobileNetV3_large_x0_75 | 25.8 | 11.1 |\n",
    "| <b>PPLCNet_x1_0<b> | <b>26.9<b> | <b>7.9<b> |\n",
    "\n",
    "### 2.3 语义分割\n",
    "\n",
    "语义分割的方法我们选用了 DeeplabV3+，下表展示了在 Cityscapes 数据集上、backbone 选用 PP-LCNet 与 MobileNetV3 的比较，在精度和速度方面，PP-LCNet 的优势同样明显。\n",
    "\n",
    "| Backbone | mIoU(%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|\n",
    "| MobileNetV3_large_x0_5 | 55.42 | 135 |\n",
    "| <b>PPLCNet_x0_5<b> | <b>58.36<b> | <b>82<b> |\n",
    "| MobileNetV3_large_x0_75 | 64.53 | 151 |\n",
    "| <b>PPLCNet_x1_0<b> | <b>66.03<b> | <b>96<b> |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 模型快速使用\n",
    "\n",
    "### 3.1 模型推理：\n",
    "* 安装相关 Python 包\n",
    "\n",
    "（不在Jupyter Notebook上运行时需要将\"!\"去掉。）\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果您的机器安装了 CUDA9、CUDA10 或 CUDA11，请运行以下命令安装 paddle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install paddlepaddle-gpu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "您的机器是CPU，请运行以下命令安装 paddle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install paddlepaddle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "安装 paddleclas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "!pip install paddleclas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 快速体验\n",
    "\n",
    "恭喜！ 您已经成功安装了 PaddleClas，接下来快速体验图像分类效果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "!wget https://gitee.com/paddlepaddle/PaddleClas/raw/release/2.5/docs/images/inference_deployment/whl_demo.jpg\n",
    "!paddleclas --model_name=PPLCNet_x1_0  --infer_imgs=\"./whl_demo.jpg\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上述命令的运行结果如下所示：\n",
    "\n",
    "class_ids: [8, 7, 86, 81, 85], scores: [0.91347, 0.03779, 0.0036, 0.00117, 0.00112], label_names: ['hen', 'cock', 'partridge', 'ptarmigan', 'quail'], filename: docs/images/inference_deployment/whl_demo.jpg\n",
    "Predict complete!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 模型训练\n",
    "* PP-LCNet 系列模型基于 PaddleClas 实现，模型训练的具体信息请参考[模型训练、评估和预测](https://github.com/paddlepaddle/paddleclas/blob/release%2F2.5/docs/zh_CN/models/ImageNet1k/PP-LCNet.md#3-%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83%E8%AF%84%E4%BC%B0%E5%92%8C%E9%A2%84%E6%B5%8B)。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 模型原理"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.1 总体结构\n",
    "\n",
    "PP-LCNet 网络的整体结构如下图所示：\n",
    "\n",
    "<div align=\"center\">\n",
    "<img src=\"https://user-images.githubusercontent.com/12560511/200734729-62f11a96-6c93-4061-8fc7-ca5d2c41d92b.png\"  width = \"80%\"  />\n",
    "</div>\n",
    "\n",
    "### 4.2 模型细节\n",
    "\n",
    "PP-LCNet 网络的结果设计基于大量实验结果，通过对网络不同结构进行实验，总结出了 4 个几乎不增加模型延迟但可以提高模型性能的策略，通过融合这 4 个策略得到了 PP-LCNet 模型。下面对这四条策略一一介绍：\n",
    "\n",
    "#### 4.2.1 更好的激活函数\n",
    "\n",
    "自从卷积神经网络使用了 ReLU 激活函数后，网络性能得到了大幅度提升，近些年 ReLU 激活函数的变体也相继出现，如 Leaky-ReLU、P-ReLU、ELU 等，2017 年，谷歌大脑团队通过搜索的方式得到了 swish 激活函数，该激活函数在轻量级网络上表现优异，在 2019 年，MobileNetV3 的作者将该激活函数进一步优化为 H-Swish，该激活函数去除了指数运算，速度更快，网络精度几乎不受影响。我们也经过很多实验发现该激活函数在轻量级网络上有优异的表现。所以在 PP-LCNet 中，我们选用了该激活函数。\n",
    "\n",
    "#### 4.2.2 合适的位置添加 SE 模块\n",
    "SE 模块是 SENet 提出的一种通道注意力机制，可以有效提升模型的精度。但是在 Intel CPU 端，该模块同样会带来较大的延时，如何平衡精度和速度是我们要解决的一个问题。虽然在 MobileNetV3 等基于 NAS 搜索的网络中对 SE 模块的位置进行了搜索，但是并没有得出一般的结论，我们通过实验发现，SE 模块越靠近网络的尾部对模型精度的提升越大。下表也展示了我们的一些实验结果：\n",
    "\n",
    "| SE Location       | Top-1 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|\n",
    "| 1100000000000     | 61.73           | 2.06         |\n",
    "| 0000001100000     | 62.17           | 2.03         |\n",
    "| <b>0000000000011<b>     | <b>63.14<b>           | <b>2.05<b>         |\n",
    "| 1111111111111     | 64.27           | 3.80         |\n",
    "\n",
    "最终，PP-LCNet 中的 SE 模块的位置选用了表格中第三行的方案。\n",
    "\n",
    "#### 4.2.3 合适的位置添加更大的卷积核\n",
    "\n",
    "在 MixNet 的论文中，作者分析了卷积核大小对模型性能的影响，结论是在一定范围内大的卷积核可以提升模型的性能，但是超过这个范围会有损模型的性能，所以作者组合了一种 split-concat 范式的 MixConv，这种组合虽然可以提升模型的性能，但是不利于推理。我们通过实验总结了一些更大的卷积核在不同位置的作用，类似 SE 模块的位置，更大的卷积核在网络的中后部作用更明显，下表展示了 5x5 卷积核的位置对精度的影响：\n",
    "\n",
    "| large-kernel Location       | Top-1 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|\n",
    "| 1111111111111     | 63.22           | 2.08         |\n",
    "| 1111111000000     | 62.70           | 2.07        |\n",
    "| <b>0000001111111<b>     | <b>63.14<b>           | <b>2.05<b>         |\n",
    "\n",
    "实验表明，更大的卷积核放在网络的中后部即可达到放在所有位置的精度，与此同时，获得更快的推理速度。PP-LCNet 最终选用了表格中第三行的方案。\n",
    "\n",
    "\n",
    "#### 4.2.4 GAP 后使用更大的 1x1 卷积层\n",
    "在 GoogLeNet 之后，GAP（Global-Average-Pooling）后往往直接接分类层，但是在轻量级网络中，这样会导致 GAP 后提取的特征没有得到进一步的融合和加工。如果在此后使用一个更大的 1x1 卷积层（等同于 FC 层），GAP 后的特征便不会直接经过分类层，而是先进行了融合，并将融合的特征进行分类。这样可以在不影响模型推理速度的同时大大提升准确率。 \n",
    "\n",
    "\n",
    "经过以上四个方面的改进，得到了 PP-LCNet。下表进一步说明了每个方案对结果的影响：\n",
    "\n",
    "| Activation | SE-block | Large-kernel | last-1x1-conv | Top-1 Acc(\\%) | Latency(ms) |\n",
    "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
    "| 0       | 1       | 1               | 1                | 61.93 | 1.94 |\n",
    "| 1       | 0       | 1               | 1                | 62.51 | 1.87 |\n",
    "| 1       | 1       | 0               | 1                | 62.44 | 2.01 |\n",
    "| 1       | 1       | 1               | 0                | 59.91 | 1.85 |\n",
    "| <b>1<b>       | <b>1<b>       | <b>1<b>               | <b>1<b>                | <b>63.14<b> | <b>2.05<b> |\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 注意事项\n",
    "PP-LCNet 系列模型在 Intel CPU 端延时测试基于 Intel Xeon Gold 6148 硬件平台完成，推理框架使用 PaddlePaddle，开启 MKLDNN 加速，推理 batch size 为 1，线程数为 10。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 相关论文以及引用信息\n",
    "\n",
    "@misc{cui2021pplcnet,\n",
    "      title={PP-LCNet: A Lightweight CPU Convolutional Neural Network},\n",
    "      author={Cheng Cui and Tingquan Gao and Shengyu Wei and Yuning Du and Ruoyu Guo and Shuilong Dong and Bin Lu and Ying Zhou and Xueying Lv and Qiwen Liu and Xiaoguang Hu and Dianhai Yu and Yanjun Ma},\n",
    "      year={2021},\n",
    "      eprint={2109.15099},\n",
    "      archivePrefix={arXiv},\n",
    "      primaryClass={cs.CV}\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
